#include "tokenparser.h"
#include <set>
TokenParser::TokenParser()
{

}

/**
 * @brief 根据settings解析单词
 * @param text
 * @param items
 * @return
 */
bool TokenParser::parse(const std::string &text, TokenParserItems &items, const std::map<std::string, int>& tokenInfos)
{
    int pos = 0;
    std::string::size_type prePos = 0;
    std::string::size_type index = 0;


    // 1.第一次遍历获取所有的单词位置
    std::set<TokenParserItem> firstPass;
    auto it = tokenInfos.begin();
    while(it != tokenInfos.end()){
        const std::string key = it->first;
        int val = it->second;
        index = text.find(key, pos);
        if(index!=std::string::npos){
            TokenParserItem item;
            item.start = index;
            item.len   = key.length() ;
            item.color = val;
            item.token = key;

            firstPass.insert(item);
        }
        ++it;
    }


    if(firstPass.size()<=0)
    {
            TokenParserItem item;
            item.start = 0;
            item.len   = text.length() ;
            item.color = -1;
            item.token = text;
            items.items.push_back(item);
       return false;
    }


    // 2.根据排好序的token信息重建tokens列表
    auto item = firstPass.begin();
    while(item!=firstPass.end())
    {
        if(prePos!=item->start)
        {
            TokenParserItem preItem;
            preItem.token = text.substr(prePos, item->start-prePos);
            preItem.color = -1;
            items.items.push_back(preItem);
        }
        items.items.push_back(*item);
        prePos = item->start + item->len;

        ++item;
    }

    if(prePos<text.length()){
        TokenParserItem item;
        item.start = prePos;
        item.len   = text.length() - prePos;
        item.color = -1;
        item.token = text.substr(item.start, item.len);
        items.items.push_back(item);
    }

    return true;
}

bool TokenParser::isExclude(const std::string &text, const std::vector<std::string> &excludes)
{
    for(const std::string& keyword : excludes){
        if(text.find(keyword)!=std::string::npos)
            return true;
    }
    return false;
}

bool operator <(const TokenParserItem &first, const TokenParserItem &second)
{
    return  first.start < second.start;
}
